iT邦幫忙

1

【JavaScript】淺層拷貝與深層拷貝

  • 分享至 

  • xImage
  •  

【前言】
本系列為個人前端學習之路的學習筆記,在過往的學習過程中累積了很多筆記,如今想藉著IT邦幫忙這個平台做整理+再複習。
本系列標題一律以【】標示該篇文章主要涉及的內容,例如【JavaScript】、【Vue】等等。
若內容有誤,還麻煩各路大神不吝於點出問題,感激不敬。


為何需要拷貝?

在JavaScript中,不同於純值,物件是傳參考

let obj1 = {
    num: 1
};
obj2 = obj1;
obj2.num = 2;
console.log(obj1.num); //2

在這個案例中,我們將obj賦值到obj2上,並且修改obj2屬性的值
但因為物件傳參考的特性,原本的obj1也會一起改到
為了避免這樣的情況,我們希望把兩個相同的物件分離(確實的複製一份,可以各自獨立修改)
這時候就要使用拷貝,通常分為淺層拷貝和深層拷貝

淺層拷貝

淺層拷貝只有複製第一層,第二層內容仍是指向原本的參考
如果物件內屬性的值是物件,那它的參考位置也會一同被複製過去,因此在這個案例中innerObj仍就是同一個物件

let obj1 = {
    num: 1,
    innerObj: {
        text: "inner"
    }
};
let obj2 = {};
for(let key in obj1){ 
	obj2[ key ] = obj1[ key ];
}
obj2.num = 2;
obj2.innerObj.text = "淺層拷貝無法保護到";
console.log(obj1.num); //1
console.log(obj1.innerObj.text); //淺層拷貝無法保護到

在這個案例中obj1的num屬性在淺層拷貝時被拷貝到了obj2,因此修改obj2的num並不會讓obj1的num產生影響
但因為innerObj是物件,因此拷貝過去的也是參考位置,obj1和obj2的innerObj還是同一個物件,因此還是會互相影響

淺層拷貝方法

這裡列舉幾個淺層拷貝的方法,第一個就是上面用的:

let 新物件 = {}; //創造一個新的參考位置
//把舊物件的第一層屬性複製過去
for(let key in 舊物件){ 
	新物件[ key ] = 舊物件[ key ];
}

此外,ES6也有新的寫法,為let 新物件 = Object.assign( {} , 舊物件 )

let obj2 = Object.assign({},obj1);

或是使用展開:

let obj2 = {...obj1};

深層拷貝

深層拷貝會將新物件與舊物件完全徹底斷開關係
即便有第三第四層的物件也不會出現問題

let obj1 = {
    num: 1,
    innerObj: {
        text: "inner"
    }
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.num = 2;
obj2.innerObj.text = "深層拷貝才保護得到";
console.log(obj1.num); //1
console.log(obj1.innerObj.text); //inner

深層拷貝會透過JSON.parseJSON.stringify將元物件轉成字串再轉回來,此時新物件與元物件就毫無關聯


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
qpalzm
iT邦研究生 5 級 ‧ 2022-03-31 15:42:40

之前我也研究過,順便來分享一下,有位大大提供另一種的解法說明~歡迎參考喔~
https://ithelp.ithome.com.tw/questions/10203585

感謝分享!

我要留言

立即登入留言